package JasPerl::PSGI::Response;

use strict;
use warnings;

use parent qw(JasPerl::Response);

use Encode;
use Plack::Response;
use JasPerl::Exceptions;

my $DEFAULT_ENCODING = find_encoding('ISO-8859-1');

sub new {
    my ($class) = @_;

    bless {
        encoding => $DEFAULT_ENCODING,
        response => Plack::Response->new(200)
    }, $class;
}

sub get_character_encoding {
    return $_[0]->{encoding}->mime_name;
}

sub get_content_type {
    return scalar $_[0]->{response}->content_type;
}

sub get_locale {
    return $_[0]->{locale} || $_[0]->SUPER::get_locale();
}

sub get_writer {
    return $_[0];
}

sub is_committed {
    return exists $_[0]->{body};
}

sub reset {
    my $self = shift;
    JasPerl::Util::IllegalStateException->throw()
        if $self->is_committed();
    $self->{response} = Plack::Response->new(200);
    delete $self->{body};
}

sub set_character_encoding {
    my ($self, $charset) = @_;

    if (!$self->is_committed()) {
        $self->{encoding} = find_encoding($charset);
    }
}

sub set_content_length {
    $_[0]->{response}->content_length($_[1]);
}

sub set_content_type {
    # FIXME: charset)
    warn "set content type: ", @_;
    $_[0]->{response}->content_type($_[1]);
}

sub set_locale {
    my ($self, $locale) = @_;
    $self->{locale} = $locale;
    $self->{response}->headers->content_language($locale->as_language_tag);
}

###  HTTP interface

sub add_cookie {
    my ($self, $cookie) = @_;
    $self->{response}->cookies->{$cookie->get_name()} = { $cookie->as_hash };
}

sub add_header {
    $_[0]->{response}->headers->push_header($_[1], $_[2]);
}

sub contains_header {
    return defined $_[0]->{response}->header($_[1]);
}

# encode_redirect_url, encode_url handled by base class

sub send_error {
    # FIXME
    my ($self, $sc, $msg) = @_;
    $_[0]->set_status($sc);
    $_[0]->{body} = [ $msg ] if $msg;
}

sub send_redirect {
    my ($self, $location) = @_;
    # TODO: spec...
    $_[0]->redirect($_[1]);
    $_[0]->{body} = [ ];
}

sub set_header {
    $_[0]->{response}->headers->header($_[1]);
}

sub set_status {
    $_[0]->{response}->status($_[1]);
}

# psgi/plack methods
sub finalize {
    my $self = shift;
    $self->{response}->body($self->{body});
    return $self->{response}->finalize;
}

# writer/output methods

sub flush {
    return $_[0]->{body} ||= [ ];
}

sub write {
    my ($self, $buf, $len, $off) = @_;
    $buf = substr($buf, $off || 0, $len)
        if defined $len;
    $buf = $self->{encoding}->encode($buf);
    return push @{$self->{body}}, $buf;
}

1;
